package orm_iray_proxy

import (
	"database/sql"
	"fmt"
	"github.com/go-sql-driver/mysql"
	"go-tool/db"
	"strconv"
	"time"
)

type JobInfo struct {
	Id               int
	JobId            string          `db:"job_id"`
	Ip               sql.NullString  `db:"ip"`
	StartTime        mysql.NullTime  `db:"start_time"`
	SubmitTime       mysql.NullTime  `db:"submit_time"`
	FinishedTime     mysql.NullTime  `db:"finished_time"`
	Width            int             `db:"width"`
	Height           int             `db:"height"`
	Priority         int             `db:"priority"`
	MaxIterations    int             `db:"max_iterations"`
	RenderTime       sql.NullFloat64 `db:"render_time"`
	AddTime          mysql.NullTime  `db:"add_time"`
	UpdateTime       mysql.NullTime  `db:"update_time"`
	JobStartTime     mysql.NullTime  `db:"job_start_time"`
	JobEndTime       mysql.NullTime  `db:"job_end_time"`
	UploadEndTime    mysql.NullTime  `db:"upload_end_time"`
	RenderType       int             `db:"render_type"`
	Retries          int             `db:"retries"`
	StrInitStartTime mysql.NullTime  `db:"str_init_start_time"`
	StrInitEndTime   mysql.NullTime  `db:"str_init_end_time"`
	StrSwitchTime    mysql.NullTime  `db:"str_swith_time"`
	StrSubmitTime    mysql.NullTime  `db:"str_submit_time"`
	ConstructIp      sql.NullString  `db:"construct_ip"`
}

func (t *JobInfo) Insert() bool {
	sqlStr := "insert into job_info (ip, job_id, start_time, submit_time, finished_time, width, height, priority, max_iterations, render_time, add_time) values (?,?,?,?,?,?,?,?,?,?)"
	_, err := db.Db.Exec(sqlStr,
		t.Ip, t.JobId, t.StartTime.Time, t.SubmitTime.Time, t.FinishedTime.Time, t.Width, t.Height, t.Priority, t.MaxIterations, t.RenderTime.Float64, time.Now())
	if err != nil {
		fmt.Printf("insert failed, err:%v\n", err)
		return false
	}
	return true
}

func (t *JobInfo) UpdateIp() bool {
	sqlStr := "update job_info set ip=? where job_id=?"
	_, err := db.Db.Exec(sqlStr,
		t.Ip, t.JobId)
	if err != nil {
		fmt.Printf("update ip failed, err:%v\n", err)
		return false
	}
	return true
}

func (t *JobInfo) Query(offset int, limit int) (rows []JobInfo, err error) {
	sqlStr := "select * from job_info order by id desc limit ?,? "
	err = db.Db.Select(&rows, sqlStr, offset, limit)
	return
}

//插入
func (t *JobInfo) InsertByConstructScene() bool {
	sqlStr := `insert into job_info (job_id, construct_ip, job_start_time, job_end_time, upload_end_time, render_type, retries, add_time) values (?,?,?,?,?,?,?,?)
			   ON DUPLICATE KEY
			   update construct_ip=?, job_start_time=?, job_end_time=?, upload_end_time=?, render_type=?, retries=?
			   `
	_, err := db.Db.Exec(sqlStr,
		t.JobId, t.ConstructIp.String, t.JobStartTime.Time, t.JobEndTime.Time, t.UploadEndTime.Time, t.RenderType, t.Retries, time.Now(),
		t.ConstructIp.String, t.JobStartTime.Time, t.JobEndTime.Time, t.UploadEndTime.Time, t.RenderType, t.Retries)
	if err != nil {
		fmt.Printf("insert failed, err:%v\n", err)
		return false
	}
	return true
}

//插入
func (t *JobInfo) InsertByConstructResult() bool {
	sqlStr := `insert into job_info (job_id, str_init_start_time, str_init_end_time, str_swith_time, str_submit_time, add_time) values (?,?,?,?,?,?)
			   ON DUPLICATE KEY
			   update str_init_start_time=?, str_init_end_time=?, str_swith_time=?, str_submit_time=?
			   `
	_, err := db.Db.Exec(sqlStr,
		t.JobId, t.StrInitStartTime.Time, t.StrInitEndTime.Time, t.StrSwitchTime.Time, t.StrSubmitTime.Time, time.Now(),
		t.StrInitStartTime.Time, t.StrInitEndTime.Time, t.StrSwitchTime.Time, t.StrSubmitTime.Time)
	if err != nil {
		fmt.Printf("insert failed, err:%v\n", err)
		return false
	}
	return true
}

/**
获取周期内最小和最大的id
*/
func (t *JobInfo) QueryOtherResultMinIdAndMaxIdByTime(startTime string, endTime string) (minId int64, maxId int64) {
	sqlStr := `SELECT MIN(id), MAX(id) FROM other_nodes_result
               WHERE update_time>=? AND update_time<? AND result_code=330`
	db.Db.QueryRow(sqlStr, startTime, endTime).Scan(&minId, &maxId)
	return
}

func (t *JobInfo) QueryConstructResultMinIdAndMaxIdByTime(startTime string, endTime string) (minId int64, maxId int64) {
	sqlStr := `SELECT MIN(id), MAX(id) FROM construct_result
               WHERE create_time>=? AND create_time<? AND code = 0 and status=0`
	db.Db.QueryRow(sqlStr, startTime, endTime).Scan(&minId, &maxId)
	return
}

func (t *JobInfo) QueryByConstruct(minId int64, maxId int64, limit int64) (rows []JobInfo, err error) {
	sqlStr := `SELECT a.id,a.job_id,a.render_type,a.priority,a.retries,a.create_time as job_start_time,a.update_time as job_end_time,
				b.update_time as upload_end_time, a.server_ip as construct_ip, b.server_ip as ip
				from construct_scene a 
				LEFT JOIN other_nodes_result b on a.job_id = b.job_id and b.result_code=330
				where a.create_time>0 and b.update_time>0 and a.id>=? and a.id<=?
				order by a.id asc
				limit ?
				`
	err = db.Db.Select(&rows, sqlStr, minId, maxId, limit)
	return
}

func (t *JobInfo) QueryByConstructResult(minId int64, maxId int64, offset int64, limit int64) (rows []JobInfo, err error) {
	sqlStr := `
			SELECT a.id, a.job_id, a.server_ip construct_ip, a.create_time as str_init_start_time, 
			b.create_time as str_init_end_time, c.create_time as str_swith_time
			, d.create_time as str_submit_time
			FROM (SELECT id,job_id,code,server_ip,create_time FROM construct_result
			where code = 0 and status=0 and id>=` + strconv.Itoa(int(minId)) + ` and id<= ` + strconv.Itoa(int(maxId)) + `
			GROUP BY job_id
			ORDER BY id desc) a
			LEFT JOIN (SELECT id,job_id,code,server_ip,create_time FROM construct_result
			where code = 106 and status=0 and id>=` + strconv.Itoa(int(minId)) + ` and id<= ` + strconv.Itoa(int(maxId)) + `
			GROUP BY job_id
			ORDER BY id desc) b ON a.job_id = b.job_id
			LEFT JOIN (SELECT id,job_id,code,server_ip,create_time FROM construct_result
			where code = 116 and status=0 and id>=` + strconv.Itoa(int(minId)) + ` and id<= ` + strconv.Itoa(int(maxId)) + `
			GROUP BY job_id
			ORDER BY id desc) c ON a.job_id = c.job_id
			LEFT JOIN (SELECT id,job_id,code,server_ip,create_time FROM construct_result
			where code = 130 and status=0 and id>=` + strconv.Itoa(int(minId)) + ` and id<= ` + strconv.Itoa(int(maxId)) + `
			GROUP BY job_id
			ORDER BY id desc) d ON a.job_id = d.job_id
			where b.create_time is true and c.create_time is true and d.create_time is true
			limit ?,?`
	err = db.Db.Select(&rows, sqlStr, offset, limit)
	return
}

func (t *JobInfo) SetRenderTypeByJobId() {
	sqlStr := `select render_type from construct_scene 
               where job_id = ?`
	db.Db.QueryRow(sqlStr, t.JobId).Scan(&t.RenderType)
}

func (t *JobInfo) SetStrInitStartTimeByJobId() {
	sqlStr := `select create_time strInitStartTime from construct_result 
               where code = 0 and status=0 and job_id = ?`
	db.Db.QueryRow(sqlStr, t.JobId).Scan(&t.StrInitStartTime)
}
